#include "Precompiled.h"
#include "Renderer.h"


Demo::Renderer::Renderer() : 
	DirectXBase(),
	m_lScene(),
	m_lCam()
{
}

void Demo::Renderer::CreateBuffers()
{
	m_lScene.ImportFbx( L"Gm_Labwork_09_Model_010.FBX" );
	auto pRoot = m_lScene.GetRootChild();

	//auto pHuman = (*pRoot->GetChildAt(0));
	//auto pMesh = pHuman->GetTypedChildContext<Eifersucht::MeshContext>();
	//pHuman->LclRotation =  DirectX::XMMatrixRotationX(-DirectX::XM_PIDIV2);
	//pHuman->LclTranslation =  DirectX::XMMatrixTranslation(0.0f, -30.0f, 0.0f);
	//pHuman->LclScale = DirectX::XMMatrixScaling(0.3f, 0.3f, 0.3f);

	m_Graph.pDevice = m_Device3.Get();
	m_Graph.pContext = m_Context3.Get();

	m_Graph.AttachRecursively(pRoot);

	//m_pModelBaseChild = nullptr;
	//auto nChildren = pRoot->GetChildrenCount();

	//for ( auto iChild = 0u; iChild < nChildren; iChild++ )
	//{
	//	auto pChild = (*pRoot->GetChildAt(iChild));
	//	AutoDebugVariable(szName) (pChild->GetName());
	//	//if (!lstrcmpW( pChild->GetName(), L"Model_Pivot_BackRight" ))
	//	if (!lstrcmpW( pChild->GetName(), L"Model_LowerBase" ))
	//	{
	//		m_pModelBaseChild = pChild;
	//		break;
	//	}
	//}

	//{
	//	auto const pMesh = m_pModelBaseChild->GetTypedChildContext<Eifersucht::MeshContext>();
	//	auto const nVertex = pMesh->vnFaces.size() * 3;
	//	auto const nFace = pMesh->vnFaces.size();

	//	{
	//		Vertex *pVertices = new Vertex[nVertex];
	//		ZeroValueArray(pVertices, nVertex);

	//		for ( auto iFace = 0u; iFace < nFace; iFace++ ) // for each face 
	//		for ( auto iFaceVertex = 0; iFaceVertex < 3; iFaceVertex++) // for each vertex in face do
	//		{
	//			auto const iVertex = iFace * 3 + iFaceVertex; // vertex id
	//			pVertices[iVertex].uControlPoint = pMesh->vnFaces[iFace].v3u1ControlPoints[2-iFaceVertex];
	//			pVertices[iVertex].f4Normal = pMesh->vnFaces[iFace].v3f4Normals[2-iFaceVertex];
	//			pVertices[iVertex].f2Tex = pMesh->vnFaces[iFace].v3f2TexCoords[2-iFaceVertex];
	//		}

	//		Demo::CreateVertexBuffer(
	//			m_Device3.Get(), nVertex, 
	//			m_SceneVertexBuffer.GetAddressOf(), 
	//			pVertices
	//			);

	//		Safe_DeleteArray(pVertices);
	//	}

	//	{
	//		auto nControlPoint = pMesh->vnControlPoints.size();
	//		ControlPoint *pControlPoints  = new ControlPoint[nControlPoint];
	//		ZeroValueArray(pControlPoints, nControlPoint);

	//		for ( auto iPoint = 0u; iPoint < nControlPoint; iPoint++ )
	//		{
	//			pControlPoints[iPoint].f4ControlPoint = pMesh->vnControlPoints[iPoint].f4Position;
	//		}

	//		Demo::CreateStructuredBuffer(
	//			m_Device3.Get(), nControlPoint, 
	//			m_ControlPointsStructBuffer.GetAddressOf(), 
	//			m_ControlPointsStructBufferSRV.GetAddressOf(), 
	//			nullptr,
	//			pControlPoints
	//			);

	//		Safe_DeleteArray(pControlPoints);
	//	}
	//}

	{
		ZeroValue(&m_lConstBuffer);
		m_lConstBuffer.f4x4World = DirectX::XMMatrixIdentity();
		m_lConstBuffer.f4x4View = DirectX::XMMatrixIdentity();
		m_lConstBuffer.f4x4Proj = DirectX::XMMatrixIdentity();

		Demo::CreateConstantBuffer(
			m_Device3.Get(), 
			m_PerModelConstBuffer.GetAddressOf(), 
			&m_lConstBuffer
			);
	}

	{
		Sehnsucht::IO::BasicLoader Loader(m_Device3.Get(), m_WicFactory2.Get());
		Loader.LoadTexture( 
			//L"ModelImageTex.bmp", 
			L"ModelImageTexGray.bmp", 
			m_ModelTex.GetAddressOf(), 
			m_ModelTexSRV.GetAddressOf() 
			);

		/*D3D11_TEXTURE2D_DESC Desc;
		m_ModelTex->GetDesc(&Desc);
		auto eFormat = Desc.Format;*/

	}

	{
		CD3D11_DEFAULT Default;
		CD3D11_SAMPLER_DESC aDesc(Default);
		D3D11_SAMPLER_DESC Desc = (D3D11_SAMPLER_DESC)aDesc;
		m_Device3->CreateSamplerState(&Desc, m_ScenePsSampler.GetAddressOf());
	}

	m_lCam.SetWindow(
		m_RenderTargetSize.width, 
		m_RenderTargetSize.height 
		);
}

void Demo::Renderer::CreateShaders()
{
	{
		D3D11_INPUT_ELEMENT_DESC l3Input[3]; ZeroValueArray(l3Input, 3);
		l3Input[0].SemanticName = "CONTROLPOINTID";
		l3Input[0].Format = DXGI_FORMAT_R32_UINT;
		l3Input[1].SemanticName = "NORMAL";
		l3Input[1].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
		l3Input[1].AlignedByteOffset = 4;
		l3Input[2].SemanticName = "TEXCOORD";
		l3Input[2].Format = DXGI_FORMAT_R32G32_FLOAT;
		l3Input[2].AlignedByteOffset = 20;

		Sehnsucht::IO::BasicLoader lLoader(
			m_Device3.Get(), m_WicFactory2.Get()
			);
		lLoader.LoadShader( 
			L"SceneVertexShader.cso", l3Input, 3, m_SceneVs.GetAddressOf(), 
			m_SceneVsLayout.GetAddressOf() 
			);
	}

	{
		Sehnsucht::IO::BasicLoader lLoader(
			m_Device3.Get(), m_WicFactory2.Get()
			);
		lLoader.LoadShader( 
			L"ScenePixelShader.cso",
			m_ScenePs.GetAddressOf()
			);
	}

	static auto s_f4Up = DirectX::XMFLOAT4(0.0f, 1.0f, 0.0f, 0.0f);
	static auto s_f4Eye = DirectX::XMFLOAT4(-30.0f, 50.0f, -100.0f, 0.0f);
	static auto s_f4Focus = DirectX::XMFLOAT4(0.0f, 1.0f, 0.0f, 0.0f);

	static auto s_vf4Focus = DirectX::XMLoadFloat4( &s_f4Focus );
	static auto s_vf4Eye = DirectX::XMLoadFloat4( &s_f4Eye );
	static auto s_vf4Up = DirectX::XMLoadFloat4( &s_f4Up );

	Reign::Vector3 lf4Eye = s_vf4Eye;
	Reign::Vector3 lf4Focus = s_vf4Focus;

	m_lCam.SetView(&lf4Eye, &lf4Focus);

	RECT rc;
	GetClientRect(m_Window, &rc);
	m_lCam.SetDragRect(rc);
	m_lCam.SetEnablePointerCapture(true);
	m_lCam._Basic_camera_proj(Reign::XM_PIDIV4, m_RenderTargetSize.width/m_RenderTargetSize.height, 0.001f, 1000.0f);
}

void Demo::Renderer::OnFrameMove( _In_ TimerViewPtr pTimer )
{
	static UInt32 s_uStride = sizeof Vertex;
	static UInt32 s_uOffset = 0;

	//m_lCam.OnFrameMove( 0.001f );
	//m_lCam.OnFrameMove( pTimer->Elapsed );
	
	/*static auto s_f4Up = DirectX::XMFLOAT4(0.0f, 1.0f, 0.0f, 0.0f);
	static auto s_f4Eye = DirectX::XMFLOAT4(-30.0f, 50.0f, -300.0f, 0.0f);
	static auto s_f4Focus = DirectX::XMFLOAT4(0.0f, 1.0f, 0.0f, 0.0f);*/

	/*m_lConstBuffer.f4x4View = DirectX::XMMatrixLookAtLH(
		DirectX::XMLoadFloat4( &s_f4Eye ),
		DirectX::XMLoadFloat4( &s_f4Focus ),
		DirectX::XMLoadFloat4( &s_f4Up )
		);*/

	m_lCam.OnFrameMove( 0.001f );

	/*
	auto f3Eye = (*m_lCam.GetEye());
	f3Eye.x = 0.0f;
	f3Eye.y = 0.0f;
	f3Eye.z = 0.0f;

	auto f3Focus = (*m_lCam.GetTarget());
	m_lCam.SetView(&f3Eye, &f3Focus);

	*/
	
	// Update camera

	//m_lConstBuffer.f4x4World = m_pModelBaseChild->LclTranslation;
	m_lConstBuffer.f4x4View = (*m_lCam.GetView());
	m_lConstBuffer.f4x4Proj = (*m_lCam.GetProjection());
	m_lConstBuffer.f4CameraPositionWorld = (*m_lCam.GetEye());

	//m_Context3->UpdateSubresource( m_PerModelConstBuffer.Get(), 0, nullptr, &m_lConstBuffer, 0, 0 );

	// Configure rendering pipeline

	m_Context3->IASetInputLayout(m_SceneVsLayout.Get());
	//m_Context3->IASetVertexBuffers(0, 1, m_SceneVertexBuffer.GetAddressOf(), &s_uStride, &s_uOffset);
	m_Context3->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
	//m_Context3->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
	m_Context3->IASetIndexBuffer(nullptr, DXGI_FORMAT_UNKNOWN, 0);

	m_Context3->VSSetShader(m_SceneVs.Get(), nullptr, 0);
	m_Context3->VSSetConstantBuffers(0, 1, m_PerModelConstBuffer.GetAddressOf());
	//m_Context3->VSSetShaderResources(0, 1, m_ControlPointsStructBufferSRV.GetAddressOf());

	m_Context3->PSSetShader(m_ScenePs.Get(), nullptr, 0);
	m_Context3->PSSetSamplers(0, 1, m_ScenePsSampler.GetAddressOf());
	m_Context3->PSSetShaderResources(0, 1, m_ModelTexSRV.GetAddressOf());

}

void Demo::Renderer::OnFrame()
{
	m_Context3.Get()->OMSetRenderTargets(
		1, m_RenderTargetView3.GetAddressOf(), 
		m_DepthStencilView3.Get()
		);

    Float32 ClearColor[4] = { 0.2f, 0.2f, 0.2f, 0.2f };

	m_Context3.Get()->ClearRenderTargetView(
		m_RenderTargetView3.Get(), 
		ClearColor
		);

	m_Context3.Get()->ClearDepthStencilView(
		m_DepthStencilView3.Get(), 
		D3D11_CLEAR_DEPTH, 
		1.0f, 0ui8
		);

	// Draw scene

	m_Graph.DrawRecursively( 
		&m_lConstBuffer, m_PerModelConstBuffer.Get()
		);

	//m_Context3->Draw(2880, 0);
	//m_Context3->Draw(36, 0);

	// Draw calls...

	Present();
}

Void  Demo::Renderer::OnPointerWheelChanged( _In_ Int16 iWheelDelta )
{
	//PrintToDebugWindowOnly8("Wheel");
	m_lCam.OnPointerWheelChanged(iWheelDelta);
}

Void Demo::Renderer::OnPointerMoved( _In_ Int16 iX, _In_ Int16 iY )
{
	//PrintToDebugWindowOnly8("Move");
	m_lCam.OnPointerMoved(iX, iY);
}

Void Demo::Renderer::OnPointerLeftButtonPressed( _In_ Int16 iX, _In_ Int16 iY )
{
	//PrintToDebugWindowOnly8("LPress");
	m_lCam.OnPointerLeftButtonPressed(iX, iY);
}

Void Demo::Renderer::OnPointerRightButtonPressed( _In_ Int16 iX, _In_ Int16 iY )
{
	//PrintToDebugWindowOnly8("RPress");
	m_lCam.OnPointerRightButtonPressed(iX, iY);
}

Void Demo::Renderer::OnPointerMiddleButtonPressed( _In_ Int16 iX, _In_ Int16 iY )
{
	//PrintToDebugWindowOnly8("MPress");
	m_lCam.OnPointerMiddleButtonPressed(iX, iY);
}

Void Demo::Renderer::OnPointerLeftButtonReleased()
{
	//PrintToDebugWindowOnly8("LRelease");
	m_lCam.OnPointerLeftButtonReleased();
}

Void Demo::Renderer::OnPointerRightButtonReleased()
{
	//PrintToDebugWindowOnly8("RRelease");
	m_lCam.OnPointerRightButtonReleased();
}

Void Demo::Renderer::OnPointerMiddleButtonReleased()
{
	//PrintToDebugWindowOnly8("MRelease");
	m_lCam.OnPointerMiddleButtonReleased();
}

